package com.fuyao.cloud.asset.purchaseorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyao.cloud.admin.api.feign.RemoteDeptService;
import com.fuyao.cloud.asset.constant.AssetConstant;
import com.fuyao.cloud.asset.constant.PurchaseConstant;
import com.fuyao.cloud.asset.contract.service.AssetContractService;
import com.fuyao.cloud.asset.dto.apply.PurchaseorderSearchDTO;
import com.fuyao.cloud.asset.entity.*;
import com.fuyao.cloud.asset.entity.ac.AssetAcList;
import com.fuyao.cloud.asset.enums.AssetStatusEnum;
import com.fuyao.cloud.asset.purchaseApply.service.AssetPurchaseapplyService;
import com.fuyao.cloud.asset.purchaseorder.mapper.AssetPurchaseorderMapper;
import com.fuyao.cloud.asset.purchaseorder.service.AssetPurchaseorderService;
import com.fuyao.cloud.asset.purchaseorderlist.service.AssetPurchaseorderListService;
import com.fuyao.cloud.asset.supplier.service.AssetSupplierService;
import com.fuyao.cloud.asset.vo.purchaseorder.*;
import com.fuyao.cloud.common.core.constant.CommonConstants;
import com.fuyao.cloud.common.core.model.BaseEntity;
import com.fuyao.cloud.common.core.util.DictItemOption;
import com.fuyao.cloud.common.core.util.R;
import com.fuyao.cloud.common.data.datascope.DataScope;
import com.fuyao.cloud.common.data.resolver.DictItemResolver;
import com.fuyao.cloud.common.data.resolver.NumberResolver;
import com.fuyao.cloud.common.data.resolver.ParamResolver;
import com.fuyao.cloud.common.security.service.CloudUser;
import com.fuyao.cloud.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 采购订单
 *
 * @author liyue
 * @date 2021-11-24 10:55:26
 */
@Service
@AllArgsConstructor
public class AssetPurchaseorderServiceImpl extends ServiceImpl<AssetPurchaseorderMapper, AssetPurchaseorder> implements AssetPurchaseorderService {

	private final AssetContractService contractService;
	private final AssetPurchaseorderListService purchaseOrderListService;
	private final AssetSupplierService supplierService;
	private final RemoteDeptService deptService;
	private final AssetPurchaseapplyService purchaseapplyService;

	@Transactional
	@Override
	public boolean save(AssetPurchaseorder entity) {
		setFieldValue(entity);
		boolean hasSave = super.save(entity);
		if (hasSave) {
			purchaseOrderListService.saveOrUpdatePurchaseOrderList(entity);
		}
		return hasSave;
	}

	@Transactional
	@Override
	public IPage<AssetPurchaseorder> page(Page page, QueryWrapper<AssetPurchaseorder> query, PurchaseorderSearchDTO searchDTO) {
		query.eq("del_flag",0);
		return this.baseMapper.selectPageByScope(page,query, new DataScope());
	}

	@Override
	public boolean updateById(AssetPurchaseorder entity) {
		setFieldValue(entity);
		boolean hasUpdate = super.updateById(entity);
		if (hasUpdate) {
			purchaseOrderListService.saveOrUpdatePurchaseOrderList(entity);
		}
		// 审批完成采购订单时修改申请订单的已采购数量。
		if(AssetStatusEnum.APPROVE.getCode().equals(entity.getStatus())){
			finishPurchaseOrder(entity);
		}
		return hasUpdate;
	}

	@Override
	public PurchaseorderCreateVO create() {
		CloudUser user = SecurityUtils.getUser();
		PurchaseorderCreateVO createVO = new PurchaseorderCreateVO();
		createVO.setCreateId(user.getId());
		createVO.setCreateBy(user.getName());
		createVO.setDeptId(user.getDeptId());
		createVO.setDeptFullname(user.getFullName());
		createVO.setCreateTime(LocalDateTimeUtil.now());
		createVO.setUnid(UUID.randomUUID().toString());
		createVO.setStatus(PurchaseConstant.PURCHASE_DEFAULT_STATUS);
		createVO.setCurrencyType(PurchaseConstant.PURCHASE_DEFAULT_CURRENCY_TYPE);
		createVO.setType(PurchaseConstant.PURCHASE_DEFAULT_TYPE);
		createVO.setDetailed(StrUtil.EMPTY);
		createVO.setDeptId(user.getDeptId());
		createVO.setDeptFullname(user.getFullName());
		createVO.setDictOption(getDictOption());

		String caseKey = ParamResolver.getStr("PURCHASEORDER_CASE_VALUE", "PO");
		Map<String, String> numberMap = NumberResolver.getNumberMap(PurchaseConstant.PURCHASE_NUMBER_TYPE, DateUtil.format(new Date(), "yyyyMM"), 5L).getData();
		createVO.setCaseid(caseKey + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + numberMap.get("code"));
		return createVO;
	}

	@Override
	public PurchaseorderCreateVO edit(Long id) {
		AssetPurchaseorder purchaseorder = this.getById(id);
		Assert.isTrue(ObjectUtils.isNotEmpty(purchaseorder), String.format("%s不合法", id));
		PurchaseorderCreateVO fyAssetPurchaseorder = new PurchaseorderCreateVO();
		BeanUtil.copyProperties(purchaseorder, fyAssetPurchaseorder);
		List<AssetPurchaseorderList> purchaseorderList = this.purchaseOrderListService.list(Wrappers.<AssetPurchaseorderList>query().lambda().eq(AssetPurchaseorderList::getParentId, purchaseorder.getId()));
		if (CollUtil.isNotEmpty(purchaseorderList)) {
			fyAssetPurchaseorder.setPurchaseOrderList(purchaseorderList);
		}
		fyAssetPurchaseorder.setDictOption(getDictOption());
		return fyAssetPurchaseorder;
	}

	@Override
	public List<PurchaseOrderExcelVO> listPurchaseOrder(QueryWrapper<AssetPurchaseorder> query) {
		List<AssetPurchaseorder> purchaseOrderList = this.baseMapper.selectListByScope(query, new DataScope());
		Map<String, List<DictItemOption>> resultMap = DictItemResolver.getDictOptionResultMap(PurchaseConstant.DICT_OPTION_TYPES);
		return purchaseOrderList.stream().map(p -> {
			PurchaseOrderExcelVO excelVO = new PurchaseOrderExcelVO();
			BeanUtil.copyProperties(p, excelVO);
			excelVO.setType(DictItemResolver.getDictOptionLabel(resultMap.get(AssetConstant.TYPE_DOCUMENT), p.getType()));
			excelVO.setStatus(DictItemResolver.getDictOptionLabel(resultMap.get(PurchaseConstant.PURCHASEORDER_STATUS), String.valueOf(p.getStatus())));
			excelVO.setMethod(DictItemResolver.getDictOptionLabel(resultMap.get(AssetConstant.PURCHASE_WAY), p.getMethod()));
			excelVO.setCurrencyType(DictItemResolver.getDictOptionLabel(resultMap.get(AssetConstant.CURRENCY_TYPE), p.getCurrencyType()));
			return excelVO;
		}).collect(Collectors.toList());
	}

	@Override
	public IPage<PurchaseOrderVO> getPurchaseOrderPage(Page page, QueryWrapper<AssetPurchaseorder> queryWrapper) {
		queryWrapper.eq("del_flag", 0);
		IPage selectPage = this.baseMapper.getPurchaseOrderPage(page, queryWrapper);
		Page resultPage = new Page(page.getCurrent(), page.getSize(), page.getTotal());
		List<AssetPurchaseorder> records = selectPage.getRecords();
		if (CollUtil.isNotEmpty(records)) {
			resultPage.setRecords(records.stream().map(t -> {
				PurchaseOrderVO resultVO = new PurchaseOrderVO();
				BeanUtil.copyProperties(t, resultVO);
				List<PurchaseOrderListVO> purchaseOrderVOList = this.purchaseOrderListService.listPurchaseOrderList(t);
				resultVO.setPurchaseOrderList(purchaseOrderVOList);
				return resultVO;
			}).collect(Collectors.toList()));
		}
		return resultPage;
	}

	@Override
	public void updateArrivedQuantity(List<AssetAcList> acList, String batchnumber) {
		LambdaQueryWrapper<AssetPurchaseorderList> lambdaQueryWrapper = Wrappers.<AssetPurchaseorderList>query().lambda().eq(AssetPurchaseorderList::getBatchnumber, batchnumber);
		List<AssetPurchaseorderList> purchaseorderList = this.purchaseOrderListService.list(lambdaQueryWrapper);
		if (CollUtil.isNotEmpty(purchaseorderList) && CollUtil.isNotEmpty(acList)) {
			acList.forEach(ac->{
				purchaseorderList.forEach(purchaseorder->{
					if(purchaseorder.getSauId().equals(ac.getSauId())){
						purchaseorder.setArrivedQuantity(ac.getArrivedQuantity());
					}
				});
			});
			this.purchaseOrderListService.saveOrUpdateBatch(purchaseorderList);
		}
	}

	@Override
	public R batchDelete(List<Long> ids) {
		List<AssetPurchaseorder> purchaseorderList = this.list(Wrappers.<AssetPurchaseorder>query().lambda().in(BaseEntity::getId, ids));
		if (CollUtil.isEmpty(purchaseorderList)) {
			return R.failed("未找到相应的采购订单数据");
		}
		CloudUser user = SecurityUtils.getUser();
		boolean allMatch = purchaseorderList.stream().allMatch(purchaseorder -> AssetStatusEnum.DRAFT.getCode().equals(purchaseorder.getStatus()) && user.getId().equals(purchaseorder.getCreateId()));
		if (!allMatch) {
			return R.failed("只能删除草稿状态且创建用户为当前用户的采购订单数据");
		}
		boolean remove = this.purchaseOrderListService.remove(Wrappers.<AssetPurchaseorderList>query().lambda().in(AssetPurchaseorderList::getParentId, ids));
		boolean delete = this.removeBatchByIds(ids);
		if (!delete && !remove) {
			return R.failed("删除失败，请检查数据有效性");
		}
		return R.ok(CommonConstants.SUCCESS, "删除成功");
	}

	/**
	 * 完成主单时更新 申请单采购数量
	 *
	 * @param entity 采购主单对象
	 */
	private void finishPurchaseOrder(AssetPurchaseorder entity) {
		LambdaQueryWrapper<AssetPurchaseorderList> lambdaQueryWrapper = Wrappers.<AssetPurchaseorderList>query().lambda().eq(AssetPurchaseorderList::getBatchnumber, entity.getBatchnumber());
		List<AssetPurchaseorderList> purchaseorderList = this.purchaseOrderListService.list(lambdaQueryWrapper);
		purchaseapplyService.updatePurchasedQuantity(purchaseorderList, entity.getBatchnumber());
	}

	private PurchaseorderCreateVO.DictOption getDictOption() {
		// 可选项和树
		PurchaseorderCreateVO.DictOption dictOption = new PurchaseorderCreateVO.DictOption();
		Map<String, List<DictItemOption>> resultMap = DictItemResolver.getDictOptionResultMap(PurchaseConstant.DICT_OPTION_TYPES);
		dictOption.setStatusList(resultMap.get(PurchaseConstant.PURCHASEORDER_STATUS));
		dictOption.setPurchaseWayList(resultMap.get(AssetConstant.PURCHASE_WAY));
		dictOption.setCurrencyTypeList(resultMap.get(AssetConstant.CURRENCY_TYPE));
		dictOption.setContractTreeList(contractService.selectContractTree(Wrappers.query(new AssetContract())));
		AssetSupplier fyAssetSupplier = new AssetSupplier();
		fyAssetSupplier.setType("V");
		dictOption.setSupplierTreeList(supplierService.selectTree(Wrappers.query(fyAssetSupplier)));
		dictOption.setDeptTreeList(deptService.tree().getData());
		return dictOption;
	}

	private void setFieldValue(AssetPurchaseorder entity) {
		String caseKey = ParamResolver.getStr("PURCHASEORDER_CASE_VALUE", "PO");
		if (StrUtil.isEmpty(entity.getBatchnumber())) {
			CloudUser user = SecurityUtils.getUser();
			String batchNumber = NumberResolver.getCodeByDateTime(caseKey, user.getId(), 5);
			entity.setBatchnumber(batchNumber);
		}
		if (ObjectUtils.isNotEmpty(entity.getContractId()) && entity.getContractId() > 0) {
			AssetContract contract = this.contractService.getById(entity.getContractId());
			entity.setContractName(contract.getName());
			entity.setContractNumber(contract.getContractId());
		}
		if (ObjectUtils.isNotEmpty(entity.getSupplierId()) && entity.getSupplierId() > 0) {
			AssetSupplier supplier = this.supplierService.getById(entity.getSupplierId());
			entity.setSupplierName(supplier.getName());
		}
		// 补充金额和清单信息
		List<AssetPurchaseorderList> purchaseOrderList = entity.getPurchaseOrderList();
		if (CollUtil.isNotEmpty(purchaseOrderList)) {
			StringBuilder detailed = new StringBuilder();
			purchaseOrderList.forEach(p -> detailed.append(p.getName()).append(","));
			detailed.deleteCharAt(detailed.length() - 1);
			// 计算总金额
			long amount = purchaseOrderList.stream().collect(Collectors.summarizingLong((AssetPurchaseorderList::getAmountLong))).getSum();
			entity.setAmount(new BigDecimal(amount));
			entity.setDetailed(detailed.toString());
		}
	}

}
